In [1]:
from PIL import Image
import cv2
import numpy as np
import matplotlib.pyplot as plt

Loading & displaying Image from disk (PILLOW)

Signature: Image.open(fp, mode='r', formats=None)

The 'Image.open' function from the Python Imaging Library (PIL) is used to open an image file and return it as a PIL Image object.

In [2]:
img = Image.open('2.jpg')
print(img)
<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=3460x2316 at 0xD3A6C59550>
In [3]:
img.show()
In [4]:
from IPython.display import display
display(img)

Loading & displaying Image from disk (OPEN CV)

To read an Image in Opencv you use the cv2.imread() function, the image will be read as a numpy array Usage:

image = cv2.imread(filename, [flag])

The Square brackets i.e. [ ] are used to denote optional parameters

Params:

  • filename: Name of the image or path to the image.
  • flag: There are numerous flags but three most important ones are these: 0,1,-1

If you pass in 1 the image is read in Color, if 0 is passed the image is read in Grayscale (Black & white) and if -1 is used to read transparent images which we will learn in the next chapter, If no parameter is passed the image will be read in Color.

Lets read an image and print it.

In [5]:
img = cv2.imread('media/M1/two.png',0)
print(img)  # Can you guess which number we just printed
[[  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0]
 [  0   0   0   0 255 255 255 255 255 255 255 255 255 255   0   0   0   0
    0   0   0   0]
 [  0   0   0 255 255   0   0   0   0   0   0   0   0 255 255 255   0   0
    0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0 255 255   0
    0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0 255 255   0
    0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0 255 255 255   0   0
    0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0 255 255 255   0   0   0   0
    0   0   0   0]
 [  0   0   0   0   0   0   0   0   0 255 255 255   0   0   0   0   0   0
    0   0   0   0]
 [  0   0   0   0   0   0   0   0 255 255   0   0   0   0   0   0   0   0
    0   0   0   0]
 [  0   0   0   0   0   0   0 255 255   0   0   0   0   0   0   0   0   0
    0   0   0   0]
 [  0   0   0   0   0 255 255 255   0   0   0   0   0   0   0   0   0   0
    0   0   0   0]
 [  0   0   0   0 255 255   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0]
 [  0   0   0   0 255   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0]
 [  0   0   0   0 255 255   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0]
 [  0   0   0   0 255 255 255 255 255 255 255 255 255 255 255 255 255 255
    0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0   0   0   0]]
In [6]:
img.shape
Out[6]:
(21, 22)
In [8]:
import matplotlib.pyplot as plt
plt.imshow(img)
Out[8]:
<matplotlib.image.AxesImage at 0xd3a846b1f0>

What just happened ? , our Image is shown in color but we know we loaded in grayscale, so the issue here is that matplotlib displays single channel images with the default color_map called Viridis, you can see it how viridis displays 0-255 image.png

In [9]:
plt.imshow(img,cmap='gray')
Out[9]:
<matplotlib.image.AxesImage at 0xd3a85291f0>
In [13]:
img = cv2.imread('2.jpg',1)
plt.imshow(img)
Out[13]:
<matplotlib.image.AxesImage at 0xd3a85f7640>

image to grayscale (PIL)

In [14]:
gray_img = Image.open('2.jpg').convert('L')
In [15]:
display(gray_img)

image to grayscale (CV)

In [34]:
img = cv2.imread('2.jpg',1)
gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
plt.imshow(gray_image, cmap='gray')
Out[34]:
<matplotlib.image.AxesImage at 0xd3a87c7c70>

Save image in different format (PIL)

In [17]:
gray_img.save('2.jpeg')

Save image in different format (CV)

In [35]:
cv2.imwrite('2.jpeg', gray_image)
Out[35]:
True

Resize Image (PIL)

In [36]:
img = Image.open('2.jpg')
# Generate a thumbnail (resize while maintaining aspect ratio)
img.thumbnail((128,128))
plt.imshow(img)
Out[36]:
<matplotlib.image.AxesImage at 0xd3a884e190>
In [37]:
img = Image.open('2.jpg')
resize = img.resize((128,128))
plt.imshow(resize)
Out[37]:
<matplotlib.image.AxesImage at 0xd3a88cd550>

Resize Image (CV)

In [38]:
img = cv2.imread('2.jpg',1)
resize = cv2.resize(img, (128,128))
plt.imshow(resize)
Out[38]:
<matplotlib.image.AxesImage at 0xd3a8945ac0>

What Just Happened here, why did our Colored image got corrupted and got this blueish makeup, the reason is simple, like I previously mentioned OpenCV displays image in BGR and matplotlib displays it in RGB. So we have to reverse our channels or transform bgr to rgb and OpenCV has just the function to that

image = cv2.cvtColor(src, COLOR_CONVERSION_FLAG)

Param:

  • src: Your Input Image
  • COLOR_CONVERSION_FLAG: The color space you will convert to, for our purpose we will use cv2.COLOR_BGR2RGB
In [39]:
RGB_image = cv2.cvtColor(resize, cv2.COLOR_BGR2RGB)
plt.imshow(RGB_image)
Out[39]:
<matplotlib.image.AxesImage at 0xd3a89bfdc0>

Normalizing images

In [42]:
img = cv2.imread('2.jpg',1)
print(img.min())
print(img.max())
0
255
In [43]:
image_float = img.astype(np.float32)
# Normalize the image to the range [0, 1]
normalized_image = image_float / 255.0

print(normalized_image.min())
print(normalized_image.max())
0.0
1.0
In [44]:
plt.imshow(normalized_image)
Out[44]:
<matplotlib.image.AxesImage at 0xd3a8a4d130>

Image Manipulation

In [49]:
im = np.array(Image.open('2.jpg').convert('L'))
In [54]:
plt.imshow(im, cmap='gray')
Out[54]:
<matplotlib.image.AxesImage at 0xd3a8c18520>
In [55]:
invert_img = 255-im
In [56]:
plt.imshow(invert_img, cmap='gray')
Out[56]:
<matplotlib.image.AxesImage at 0xd3a8c901f0>
In [78]:
img_clamp = (100.0/255) * im + 100 #clamp to interval 100...200
In [79]:
plt.imshow(img_clamp, cmap='gray')
Out[79]:
<matplotlib.image.AxesImage at 0xd3ac1f8820>
In [81]:
sq = 255.0 * (im/255.0)**2 #squared
np.max(sq)
Out[81]:
255.0
In [82]:
plt.imshow(sq, cmap='gray')
Out[82]:
<matplotlib.image.AxesImage at 0xd3ac26e700>
In [83]:
sq = 255.0 * (im/255.0)**0.5 #squared
In [84]:
plt.imshow(sq, cmap='gray')
Out[84]:
<matplotlib.image.AxesImage at 0xd3ac2e0400>

Image Augmentation

In [5]:
gray_img = Image.open('2.jpg').convert('L')
rotate180 = gray_img.rotate(180)
plt.imshow(rotate180)
Out[5]:
<matplotlib.image.AxesImage at 0x1faa14ae80>
In [6]:
rotat45 = gray_img.rotate(45)
plt.imshow(rotat45)
Out[6]:
<matplotlib.image.AxesImage at 0x1faa5f4700>
In [7]:
flipped_img = gray_img.transpose(Image.Transpose.FLIP_LEFT_RIGHT)
plt.imshow(flipped_img)
Out[7]:
<matplotlib.image.AxesImage at 0x1faa66d7f0>
In [6]:
#Augmentation using open cv
# Define augmentation functions
def rotate_image(image, angle):
    height, width = image.shape[:2]
    rotation_matrix = cv2.getRotationMatrix2D((width / 2, height / 2), angle, 1.0)
    rotated_image = cv2.warpAffine(image, rotation_matrix, (width, height))
    return rotated_image

def adjust_brightness(image, factor):
    adjusted_image = cv2.convertScaleAbs(image, alpha=factor, beta=0)
    return adjusted_image

def adjust_contrast(image, factor):
    #gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    gray_image = cv2.convertScaleAbs(image, alpha=factor, beta=0)
    adjusted_image = cv2.cvtColor(gray_image, cv2.COLOR_GRAY2BGR)
    return adjusted_image

def horizontal_flip(image):
    flipped_image = cv2.flip(image, 1)
    return flipped_image

def scale_image(image, scale_factor):
    height, width = image.shape[:2]
    new_height = int(height * scale_factor)
    new_width = int(width * scale_factor)
    scaled_image = cv2.resize(image, (new_width, new_height))
    return scaled_image

def add_gaussian_noise(image, mean=0, std=25):
    noise = np.random.normal(mean, std, image.shape).astype(np.uint8)
    noisy_image = cv2.add(image, noise)
    return noisy_image
In [7]:
# Apply augmentations and display each result
img = cv2.imread('2.jpg',1)
gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
In [12]:
def apply_augmentations_and_display(image):
    # Load the image

    # Display the original image
    plt.figure(figsize=(12, 8))
    plt.subplot(3, 3, 1)
    plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
    plt.title("Original Image")
    plt.axis("off")

    # Apply augmentations and display each result
    augmentations = [
        (rotate_image, "Rotated Image", 45),
        (adjust_brightness, "Brighter Image", 1.5),
        (adjust_contrast, "Higher Contrast Image", 1.5),
        (horizontal_flip, "Horizontally Flipped Image"),
        (scale_image, "Scaled Image", 0.8),
        (add_gaussian_noise, "Noisy Image")
    ]

    for i, (augmentation_function, title, *args) in enumerate(augmentations, start=2):
        if args:
            augmented_image = augmentation_function(image, *args)
        else:
            augmented_image = augmentation_function(image)
        plt.subplot(3, 3, i)
        plt.imshow(cv2.cvtColor(augmented_image, cv2.COLOR_BGR2RGB))
        plt.title(title)
        plt.axis("off")

    # Show the plot
    plt.tight_layout()
    plt.show()
In [13]:
# Usage example:
apply_augmentations_and_display(gray_image)

Plotting images, lines, points

In [16]:
from PIL import Image
from pylab import *

# Read image to array
im = array(Image.open('2.jpg'))

# Plot the image
imshow(im, 'gray')

# Define the coordinates for the four corners of the box
x = [1900, 2900, 2900, 1900, 1900]
y = [250, 250, 1250, 1250, 250]

# Plot the points with red star-markers
plot(x, y, 'r')

# Line plot connecting the points to form a box
plot(x[:2], y[:2], 'r')  # 1st to 2nd
plot(x[1:3], y[1:3], 'r')  # 2nd to 3rd
plot(x[2:4], y[2:4], 'r')  # 3rd to 4th
plot(x[3:], y[3:], 'r')  # 4th to 1st

# Add title and show the plot
title('Plotting: "STOP.jpg"')
show()

Image contours and histograms

In [17]:
import cv2
import matplotlib.pyplot as plt

# Load the image
image = cv2.imread('2.jpg')

# Convert the image to grayscale
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# Plot the original grayscale image
plt.figure(figsize=(12, 4))
plt.subplot(131)
plt.imshow(gray_image, cmap='gray')
plt.title('Original Grayscale Image')
plt.axis('off')

# Calculate and plot the histogram of the original grayscale image
plt.subplot(132)
plt.hist(gray_image.ravel(), bins=256, range=(0, 256), density=True, color='gray', alpha=0.7)
plt.title('Histogram of Original Grayscale Image')
plt.xlabel('Pixel Value')
plt.ylabel('Normalized Frequency')

# Perform histogram equalization
equalized_image = cv2.equalizeHist(gray_image)

# Plot the histogram-equalized image
plt.subplot(133)
plt.imshow(equalized_image, cmap='gray')
plt.title('Histogram Equalized Image')
plt.axis('off')

# Calculate and plot the histogram of the equalized image
plt.figure(figsize=(12, 4))
plt.hist(equalized_image.ravel(), bins=256, range=(0, 256), density=True, color='gray', alpha=0.7)
plt.title('Histogram of Histogram Equalized Image')
plt.xlabel('Pixel Value')
plt.ylabel('Normalized Frequency')

plt.tight_layout()
plt.show()

PCA on Images sklearn

In [31]:
import matplotlib.pyplot as plt
from sklearn.datasets import load_digits

digits = load_digits()
data = digits.data
data.shape
Out[31]:
(1797, 64)
In [32]:
#taking a sample image to view
#Remember image is in the form of numpy array.
image_sample = data[0,:].reshape(8,8)
plt.imshow(image_sample)
Out[32]:
<matplotlib.image.AxesImage at 0x388ac4c9d0>
In [34]:
#Import required modules
from sklearn.decomposition import PCA

pca = PCA(49) # we need 49 principal components.
converted_data = pca.fit_transform(digits.data)

converted_data.shape
Out[34]:
(1797, 49)
In [35]:
x = converted_data[0].reshape((7,7))
In [38]:
plt.imshow(x)
Out[38]:
<matplotlib.image.AxesImage at 0x388d8edc70>

Image Compression

In [61]:
# Load the image
image = cv2.imread('2.jpg')
print(image.shape)
# Splitting the image in R,G,B arrays.
blue,green,red = cv2.split(image)
#it will split the original image into Blue, Green and Red arrays.
(2316, 3460, 3)
In [62]:
#initialize PCA with first 100 principal components
pca = PCA(100)

#Applying to red channel and then applying inverse transform to transformed array.
red_transformed = pca.fit_transform(red)
red_inverted = pca.inverse_transform(red_transformed)

#Applying to Green channel and then applying inverse transform to transformed array.
green_transformed = pca.fit_transform(green)
green_inverted = pca.inverse_transform(green_transformed)

#Applying to Blue channel and then applying inverse transform to transformed array.
blue_transformed = pca.fit_transform(blue)
blue_inverted = pca.inverse_transform(blue_transformed)
In [63]:
img_compressed = (dstack((red_inverted, red_inverted, red_inverted))).astype(uint8)
img_compressed.shape
Out[63]:
(2316, 3460, 3)
In [65]:
#viewing the compressed image
plt.imshow(img_compressed)
Out[65]:
<matplotlib.image.AxesImage at 0x388fe7b400>
In [ ]: